const webpack = require('webpack');
// 编译进度条
const ProgressBarWebpackPlugin = require('progress-bar-webpack-plugin');
// 设置 MiniCssExtractPlugin 插件的 filename 选项来指定CSS文件的输出路径和文件名
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 添加 eslint-webpack-plugin 插件实例
const ESLintPlugin = require('eslint-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const path = require('path');

// 环境变量注入
const setEnv = (env) => {
	let envObj = {};
	for (const key in env) {
		if (Object.hasOwnProperty.call(env, key)) {
			const element = env[key];
			envObj['process.env.' + key] = JSON.stringify(element);
		}
	}

	return envObj;
};

// 配置入口
const setEntry = (env) => {
	return {
		index: './src/index.tsx',
		base: './src1/index.tsx'
	}[env.REACT_APP_ENTRY];
};

// 配置打包
const setOutputPath = (env) => {
	return {
		index: 'dist',
		base: 'base'
	}[env.REACT_APP_ENTRY];
};

module.exports = (env, argv) => {
	return {
		entry: setEntry(env),
		output: {
			filename: 'js/[name][hash:5].js',
			path: path.resolve(__dirname, '..', setOutputPath(env)),
			clean: true,
			publicPath: '/'
		},
		plugins: [
			new HtmlWebpackPlugin({
				title: 'My App',
				filename: 'index.html',
				template: './public/index.html',
				favicon: path.resolve(__dirname, '..', 'public/favicon.png'),
				// chunks: ['index'], //配置html需要引入的chunk,index 是 entry中的key
				// 这里可以设置其他的HtmlWebpackPlugin配置项
				cdn: cdn // 将cdn数组作为HtmlWebpackPlugin的自定义配置项
			}),
			new ProgressBarWebpackPlugin(),
			// css压缩
			new MiniCssExtractPlugin({
				filename: 'css/[name][hash:5].css',
				chunkFilename: 'css/[name][hash:5].css'
			}),
			new ESLintPlugin({
				extensions: ['.js', '.ts', '.tsx'],
				files: ['/src', '/src1']
			}),
			// 环境注入
			new webpack.DefinePlugin({
				...setEnv(env)
				// 'process.env.REACT_APP_BASE_API': JSON.stringify('/dev-api')
				// 添加其他环境变量
			})
		],
		resolve: {
			// 配置别名
			alias: {
				'@': path.resolve(__dirname, '..', 'src'),
				'~': path.resolve(__dirname, '..', 'src1'),
				img: path.resolve(__dirname, '..', 'src/asset/image')
			},
			// 引入文件忽略文件扩展名
			extensions: ['.js', '.ts', '.jsx', '.tsx', '.json']
		},
		module: {
			rules: [
				{
					test: /\.md$/,
					exclude: /node_modules/,
					use: ['html-loader', 'markdown-loader'] // 或者 'markdown-it-loader'
				},
				{
					test: /\.pdf$/,
					exclude: /node_modules/,
					type: 'asset/resource', // 或者 'url-loader'
					generator: {
						filename: 'pdfs/[name][hash:5][ext]'
					}
				},
				{
					test: /\.(jsx|tsx|ts)?$/,
					exclude: /node_modules/,
					use: {
						loader: 'babel-loader',
						options: {
							presets: [
								'@babel/preset-env',
								[
									'@babel/preset-react',
									{
										runtime: 'automatic'
									}
								],
								'@babel/preset-typescript'
							],
							plugins: ['@babel/plugin-transform-runtime']
						}
					}
				},
				// 配置 css-loader 和 style-loader
				// 配置 sass-loader 和 css-loader 和 style-loader
				{
					test: /\.css$/,
					use: [
						...getStyleLoaders(
							{
								importLoaders: 2, // 指定在 CSS 中 @import 的文件也要被 css-loader 处理，默认为 0。
								// 启用 CSS 模块化，默认为 false。
								modules: {
									mode: 'icss',
									localIdentName: '[path][name]__[local]--[hash:5]'
								}
							},
							argv.mode
						)
					]
				},
				{
					test: /\.scss$/,
					use: [
						// 根据运行环境判断使用那个 loader
						...getStyleLoaders({
							importLoaders: 2, // 指定在 CSS 中 @import 的文件也要被 css-loader 处理，默认为 0。
							// 启用 CSS 模块化，默认为 false。
							modules: {
								mode: 'local',
								localIdentName: '[path][name]__[local]--[hash:5]'
							}
						}),
						'sass-loader'
					]
				},
				// 图片打包配置
				{
					test: /\.(png|jpg|gif)$/i,
					exclude: /node_modules/,
					type: 'asset/inline',
					generator: {
						filename: 'image/[name][hash:5][ext]'
					},
					parser: {
						dataUrlCondition: {
							maxSize: 1024 // 1kb
						}
					}
				},
				{
					test: /\.(png|jpg|gif)$/i,
					exclude: /node_modules/,
					type: 'asset/resource',
					generator: {
						filename: 'image/[name][hash:5][ext]'
					}
				},
				// svg-loader
				{
					test: /\.svg$/i,
					exclude: /node_modules/,
					type: 'asset/source'
				}
			]
		},

		cache: {
			/*
    webpack5 较于 webpack4,新增了持久化缓存、改进缓存算法等优化,通过配置 webpack 持久化缓存,来缓存生成的 webpack 模块和 chunk,
    改善下一次打包的构建速度,可提速 90% 左右,配置也简单
    */
			type: 'filesystem' // 使用文件缓存
		}
	};
};

const getStyleLoaders = (cssLoaderOpts, mode) => {
	const loaders = [
		// 开发环境使用style-looader,打包模式抽离css
		mode === 'development' ? 'style-loader' : MiniCssExtractPlugin.loader,
		{
			/** 三个作用：
			 * 1. CSS 模块化：将 CSS 模块化可以避免命名冲突，提高代码复用性。
			 * 2. 自动添加浏览器前缀：在 CSS 样式中自动添加浏览器前缀，以提高浏览器兼容性。
			 * 3. 将 CSS 中的 URL 转换成 require：将 CSS 中的图片路径转换成 Webpack 所需的 require 路径。
			 */
			loader: 'css-loader',
			options: cssLoaderOpts
		},
		{
			loader: 'postcss-loader',
			options: {
				postcssOptions: {
					// 添加 autoprefixer 插件
					plugins: [require('tailwindcss'), require('autoprefixer')]
				}
			}
		}
	];

	return loaders;
};

const cdn = {
	js: [
		// {
		// 	url: 'http://114.132.242.253:81/wangeditor.js',
		// 	defer: true
		// },
		// {
		// 	url: 'http://114.132.242.253:81/g2plot.min.js'
		// }
	],
	css: [
		// 编辑器
		// {
		// 	url: 'http://114.132.242.253:81/wangeditor.css',
		// 	rel: 'prefetch'
		// }
	]
};
